<?php

namespace api\components;

use api\components\utils\Coordinate;
use api\components\utils\GeoTransUtil;
use yii\helpers\ArrayHelper;


class GeoService
{
    /**
     * 地球半径 米
     */
    const EARTH_RADIUS = 6367000;

    /**
     * 获取两个坐标点的距离
     * @param array $point1   [lng,lat]
     * @param array $point2   [lng,lat]
     * @return int
     * @throws
     */
    public function getDistance(array $point1, array $point2): int
    {
        if(count($point1)!==2 || count($point2)!==2){
            throw new \Exception('Unavailable point arr [lng,lat]');
        }
        list($lng1, $lat1) = $point1;
        list($lng2, $lat2) = $point2;
        $lat1 = $this->rad($lat1);
        $lng1 = $this->rad($lng1);
        $lat2 = $this->rad($lat2);
        $lng2 = $this->rad($lng2);


        $calcLongitude = $lng2 - $lng1;
        $calcLatitude = $lat2 - $lat1;

        $stepOne = pow(sin($calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude / 2), 2);

        $stepTwo = 2 * asin(min(1, sqrt($stepOne)));

        $calculatedDistance = self::EARTH_RADIUS * $stepTwo;

        return round($calculatedDistance);
    }

    /**
     * GPS 坐标系转 高德坐标系
     * @param $lng
     * @param $lat
     * @return array
     */
    public function gps2gcj($lng, $lat)
    {
        $form = new Coordinate($lat,$lng);
        $form = GeoTransUtil::wgsTOgcj($form);
        return [$form->y, $form->x];
    }

    /**
     * GPS 坐标系转 高德坐标系 (批量)
     * @param $array
     * @return array
     */
    public function gpsbatch2gcj($array)
    {
        $data = [];
        if(count($array) > 0){
            foreach ($array as $row){
                $form = new Coordinate($row[1],$row[0]);
                $form = GeoTransUtil::wgsTOgcj($form);
                $data[] = [$form->y,$form->x];
            }
        }
        return $data;
    }

      /**
     * GPS 坐标系转 城地坐标系
     * @param $lng
     * @param $lat
     * @return array
     */
    public function gps2cd($lng, $lat)
    {
        $form = new Coordinate($lat,$lng);
        $form = GeoTransUtil::wgsTOcd($form);
        return [$form->y, $form->x];
    }

    /**
     * 城地 坐标系转 GPS坐标系
     * @param $lng
     * @param $lat
     * @return array
     */
    public function cd2gps($lng, $lat)
    {
        $form = new Coordinate($lat,$lng);
        $form = GeoTransUtil::cd2wgs($form);
        return [$form->y ?? null, $form->x ?? null];
    }

    /**
     * 高德 坐标系转 GPS坐标系
     * @param $lng
     * @param $lat
     * @return array
     */
    public function gcj2gps($lng, $lat)
    {
        $form = new Coordinate($lat,$lng);
        $form = GeoTransUtil::gcjTOwgs($form);
        return [$form->y, $form->x];
    }

    /**
     * GPS 坐标系转 城地坐标系(批量)
     * @param $array
     * @return array
     */
    public function gpsbatch2cd($array)
    {
        $form = GeoTransUtil::batchWgsTOcd($array);
        return $form;
    }

    /**
     * 经纬度转换成角度
     * @param $value
     * @return float|int
     */
    private function rad($value)
    {
        return $value * pi()/180;
    }

     /**
     * 城地 坐标系 请求城地详情接口
     * @param $lng
     * @param $lat
     * @return array
     */
    public function getGeoInfo($lng, $lat)
    {
        return GeoTransUtil::getGeoInfo($lng, $lat);
    }


    /**
     * 通过地址反查坐标
     * @param $address
     */
    public function getCoodFromAddress($address)
    {
        return GeoTransUtil::getCoodFromAddress($address);
    }

    public static function getInfoByAddress(array $params)
    {
        $baseUrl = \Yii::$app->params['CD_TRANSFORM'];
        $url = $baseUrl . 'coordinateByAddress?ruleType=0&address=' . urlencode($params['address']);
        $response = (new Request())->request($url, 'get', $params);
        if ($response) {
            $response = json_decode($response, true);
            if (ArrayHelper::getValue($response, 'code') !== 20000) {
                $code = ArrayHelper::getValue($response, 'code');
                $message = ArrayHelper::getValue($response, 'msg');
                throw new \Exception($message);
            }
            return $response['data'];
        } else {
            return false;
        }
    }

    public static function getInfoByCoord(array $params)
    {
        $baseUrl = \Yii::$app->params['CD_TRANSFORM'];
        $url = $baseUrl . 'coordinateByType';
        $curlData = [
            'ruleType' => "0",
            'geometry' => [
                'x' => $params['x'] ?? $params['lng'],
                'y' => $params['y'] ?? $params['lat'],
            ],
            'extObject' => []
        ];
        $response = (new Request())->rawRequest($url, json_encode($curlData));
        if ($response) {
            $response = json_decode($response, true);
            if (ArrayHelper::getValue($response, 'code') !== 20000) {
                $code = ArrayHelper::getValue($response, 'code');
                $message = ArrayHelper::getValue($response, 'msg');
                throw new \Exception($message);
            }
            return $response['data'];
        } else {
            return false;
        }
    }

    //根据坐标获取区街道
    public static function getAreaByCoord($params) {
        $result = [];
        $info = self::getInfoByCoord($params);
        if (!empty($info)) {
            $result['地址'] = $info['地址'];
        }

        $lng = $params['x'] ?? $params['lng']; //经度
        $lat = $params['y'] ?? $params['lat']; //纬度

        $url = DATA_CENTER_HOST . '/united-ciimc-api/v1/generic-query';
        $reqParams['token'] = DATA_CENTER_TOKEN;
        $reqParams['table'] = 'area';
        $reqParams['filter'] = "simple.messageType=eq.街道&geoSelecter=point[{$lng},{$lat}]polygon~intersects";
        $reqParams['limit'] = 1;

        $request = new Request();
        $url = $url . '?' . http_build_query($reqParams);
        $response = $request->request($url, 'GET');
        $response = json_decode($response, true);
        if (isset($response['data']['messages']) && !empty($response['data']['messages'])) {
            $message = $response['data']['messages'][0];
            $result['区县名称'] = isset($message['data']['area_district']['areaName']) ? $message['data']['area_district']['areaName'] : '';
            $result['区代码'] = isset($message['data']['area_district']['rawIdentity']) ? $message['data']['area_district']['rawIdentity'] : '';

            $result['街道名称'] = isset($message['data']['town']['areaName']) ? $message['data']['town']['areaName'] : '';
            $result['街道代码'] = isset($message['data']['town']['rawIdentity']) ? $message['data']['town']['rawIdentity'] : '';
        }

        return $result;
    }

}
